package 传智播客_黑马.java高级.多线程;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class 线程同步 {
    //用来解决线程安全问题
    /*
    1 同步代码块
        synchronized
        注意:
            1 通过代码块中的括号可以放任意对象
            2 但是必须保证多个线程使用的是同一对象
            3 作用
                把同步代码锁住,只让一个线程在同步代码块中执行
    2 同步方法
        1 访问了共享数据的代码抽取出来,放到一个方法中
        2 在方法上添加synchronized修饰符

        格式:定义方法的格式
        修饰符:synchronized 返回值类型 方法名称{
            方法体
            }
    3 lock锁机制
        1 在成员位置创建一个ReentrantLock对象
        2 在可能会出现安全问题的代码前调用lock接口中的方法lock获取锁
        3 在可能出现安全问题的代码后调用lock接口中的方法unlock释放锁
     */

    //实现买票案例
    class Runimpl implements Runnable{
        //定义共享票源
        private int ticket = 100;

        //1 创建任意对象
//        Object obj = new Object();


        //3 创建lock锁对象
        Lock lock = new ReentrantLock();
        //设置线程任务
        @Override
        public void run() {
//            synchronized (obj){
//                //提高概率
//                try {
//                    Thread.sleep(10);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                while(true){
//                    if(ticket>0){
//                        System.out.println(Thread.currentThread().getName()+"-->正在卖"+(ticket--)+"张票");
//                    }
//                }
//            }

            //2 同步方法 锁对象为第一个调用者  静态方法的锁对象是本类的class属性
//            buyTicket();

            //提高概率
            lock.lock();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            while(true){
                if(ticket>0){
                    System.out.println(Thread.currentThread().getName()+"-->正在卖"+(ticket--)+"张票");
                }
                else break;
            }

            lock.unlock();
        }
        public synchronized void buyTicket(){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            while(true){
                if(ticket>0){
                    System.out.println(Thread.currentThread().getName()+"-->正在卖"+(ticket--)+"张票");
                }
            }
        }
    }


    public void test(){
        Runimpl runimpl = new Runimpl();
        Thread thread1 = new Thread(runimpl);
        Thread thread2 = new Thread(runimpl);
        Thread thread3 = new Thread(runimpl);
        thread1.start();
        thread2.start();
        thread3.start();
    }
    public static void main(String[] args) {
        new 线程安全问题().test();
    }
}
